home *** CD-ROM | disk | FTP | other *** search
/ Delphi Magazine Collection 2001 / Delphi Magazine Collection 20001 (2001).iso / DISKS / ISSUE08 / DATADICT / DBUTILS.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1996-02-15  |  35.8 KB  |  961 lines

  1. unit Dbutils;
  2.  
  3. interface
  4. uses SysUtils, Classes, Forms, Controls, Dialogs, Grids,
  5.      StdCtrls, DB, DBctrls, DBTables, inifiles;
  6. const
  7.     FieldTypeStr : array[ftunknown..ftgraphic] of string[8] =
  8.       ('Unknown', 'String', 'Smallint', 'Integer', 'Word',
  9.        'Boolean', 'Float', 'Currency', 'BCD', 'Date', 'Time',
  10.        'DateTime', 'Bytes', 'VarBytes', 'Blob', 'Memo', 'Graphic');
  11.     FieldTypeLtr : array[ftunknown..ftgraphic] of string[1] =
  12.       ('U', 'S', 'I', 'N', 'W',
  13.        'L', 'F', 'C', 'B', 'D', 'T',
  14.        'A', 'Y', 'V', 'O', 'M', 'G');
  15.  
  16. type
  17.     ddfOffsets = (ddfTABLE_NAME, ddfFIELD_NAME, ddfTAG, ddfSCR_PROMPT, ddfSCR_FMT,
  18.                   ddfGRD_PROMPT, ddfGRD_WIDTH, ddfFIELD_TYPE, ddfFIELD_LEN, ddfFIELD_DEC,
  19.                   ddfFIELD_IDX, ddfIDX_EXPRES, ddfTAB_ORDER, ddfREQUIRED, ddfDEFAULT,
  20.                   ddfEDITMASK, ddfMINVAL, ddfMAXVAL, ddfVALLIST, ddfDefine, ddfValidValue,
  21.                   ddfNotes, ddfHINT, ddfHELPID, ddfHelp, ddfTable_type, ddfHASLINK,
  22.                   ddfSRCLINKTBL, ddfSRCLINKFLD, ddfIS_CALC, ddfFORMULA);
  23. const
  24.     DictTableFieldNames : array[ddfTable_Name..ddfFormula] of string[12] =
  25.        ('TABLE_NAME', 'FIELD_NAME', 'TAG', 'SCR_PROMPT', 'SCR_FMT', 'GRD_PROMPT', 'GRD_WIDTH',
  26.         'FIELD_TYPE','FIELD_LEN','FIELD_DEC','FIELD_IDX','IDX_EXPRES','TAB_ORDER','REQUIRED',
  27.         'DEFAULT','EDITMASK','MINVAL','MAXVAL','VALLIST','DEFINE', 'VALIDVALUE', 'NOTES',
  28.         'HINT','HELPID','HELP', 'TABLE_TYPE', 'HASLINK','SRCLINKTBL',
  29.         'SRCLINKFLD', 'IS_CALC', 'FORMULA' );
  30.  
  31. type
  32.   tdictctrl = class(TComponent)
  33.   private
  34.     FiniFile : TiniFile;
  35.     FCtrlDictName : Tfilename;
  36.     FDBSGGood : boolean;
  37.     FCurrentTableName,
  38.     FCurrentFieldName : string;
  39.     fCurrentField : integer;
  40.     FtempdbMemo : TDBmemo;
  41.     procedure ReadIniFile;
  42.     function getDictPath : tfilename;
  43.     procedure setDictPath( tmpstr : tfilename);
  44.     function getDictTable : tfilename;
  45.     procedure setDictTable (tmpstr : tfilename);
  46.     function getCurrentTableName : string;
  47.     function getCurrentFieldName : string;
  48.     function GetCurrentHint : string;
  49.     function GetRequired : boolean;
  50.     function GetMinVal : longint;
  51.     function GetMaxVal : longint;
  52.   protected
  53.     function setFieldDefs(var tableToDefine : Ttable; const FieldNum : integer): boolean;
  54.     function SetUpCommon(var TableToDefine : ttable; const FieldNum : integer): boolean;
  55.     function SetUpString(var TableToDefine : ttable; const FieldNum : integer): boolean;
  56.     function SetUpBoolean(var TableToDefine : ttable; const FieldNum : integer): boolean;
  57.     function SetUpDate(var TableToDefine : ttable; const FieldNum : integer): boolean;
  58.     function SetUpDateTime(var TableToDefine : ttable; const FieldNum : integer): boolean;
  59.     function SetUpTime(var TableToDefine : ttable; const FieldNum : integer): boolean;
  60.     function SetUpBytes(var TableToDefine : ttable; const FieldNum : integer): boolean;
  61.     function SetUpVarBytes(var TableToDefine : ttable; const FieldNum : integer): boolean;
  62.     function SetUpBlob(var TableToDefine : ttable; const FieldNum : integer): boolean;
  63.     function SetUpMemo(var TableToDefine : ttable; const FieldNum : integer): boolean;
  64.     function SetUpGraphic(var TableToDefine : ttable; const FieldNum : integer): boolean;
  65.     function doNumbers(const whichtype : TfieldType; var TableToDefine : ttable; const FieldNum : integer): boolean;
  66.     procedure FillTableList;
  67.   public
  68.     FDBSG : Tstringgrid;
  69.     FDBTableList : TStringList;
  70.     constructor create(aOwner : Tcomponent);
  71.     destructor putaway;
  72.     Procedure OpenDictionary(const fullTableName : string;
  73.                                var whichdb : tdatabase; var whichtable : ttable;
  74.                                var whichQuery : tquery; var whichsource : tDataSource);
  75.     Procedure FillStringGrid(var WhichTable : Ttable);
  76.     function GetFieldAsString(const fieldname: string; var whichtable : ttable): string;
  77.     function SetUpTable(var TableToSetUp : ttable): boolean;
  78.     function SetCurrentFieldTo(const tablename, fieldname : string): boolean;
  79.     function BuildEmptyTable(var TableToBuild : ttable; const TableName : string): boolean;
  80.   published
  81.     property DictPath: Tfilename read getDictPath write SetDictPath;
  82.     property DictTable: Tfilename read getDictTable write SetDictTable;
  83.     property DBSGExists : boolean read FDBSGGood;
  84.     property CurrentTableName : string read GetCurrentTableName;
  85.     property CurrentFieldName : string read GetCurrentFieldName;
  86.     property Hint : string read getCurrentHint;
  87.     property Required : boolean read getRequired;
  88.     property MinValue : longint read getMinVal;
  89.     property MaxValue : longint read getMaxVal;
  90.   end;
  91.  
  92. procedure Register;
  93.  
  94. var
  95.   DictCtrl : TDictCtrl;
  96.  
  97.     DBSGExists : boolean;
  98.  
  99. function openDB(var whichdb : tdatabase; var whichtable : ttable;
  100.                 var whichQuery : tquery; var whichsource : tDataSource;
  101.                 const pathname, tablename : string): boolean;
  102.  
  103. function FieldSummary(which : tquery): string;
  104.  
  105.  
  106. implementation
  107. uses utils, mystrng; {dbierrs, dbiprocs,dbitypes;}
  108. type
  109.   buffer = array[0..32000] of byte;
  110.  
  111. (*
  112. const
  113.    {indexes into DBSG columns}
  114.       tablename = 0;  {string 20}
  115.       tabletype = 1;  {string 20}
  116.       fieldname = 2;  {string[20];}
  117.       tag       = 3;  {string 20  tfield.tag}
  118.       scrprompt = 4;  {string[40]; {tfield.DisplayName}
  119.       scrformat = 5;  {string[80]; {tfield.DisplayText -- an editmask}
  120.       grdprompt = 6;  {string[10];}
  121.       grdwidth  = 7;  {smallint    {tfield.DisplayWidth}
  122.       fldtype   = 8;  {string[1];  {FieldTypeLtr}
  123.       fldlen    = 9;  {smallint    {tfield.size}
  124.       flddec    = 10; {smallint}
  125.       fldidx    = 11; {boolean;}
  126.       idxexp    = 12; {string;}
  127.       tab_order = 13; {integer;}
  128.       isrequired  = 14; {boolean;    {tfield.required}
  129.       defaultis   = 15; {string[80];}
  130.       editmaskis  = 16; {string[80]; {tfield.editMask}
  131.       minval    = 17; {ftfloat  tfield.minvalue}
  132.       maxval    = 18; {ftfloat  tfield.maxvalue}
  133.       vallist   = 19; {ftmemo   list of valid strings}
  134.       { define      documentation only
  135.         validvalue  documentation only
  136.         notes       documentation only}
  137.       hintTxt   = 20;  {string 120}
  138.       helpid    = 21;  {longint;}
  139.       {help, memo only used if helpid not null or 0}
  140.       haslink   = 22;  {boolean;}
  141.       srclinktbl = 23; {string[20];}
  142.       srclinkfld = 24; {string[20];}
  143.       iscalc     = 25; {boolean;}
  144.       formula    = 26; {memo only used if iscalc true}
  145. *)
  146. type
  147.    TDictCtrlStringGrid = TStringGrid;
  148.  
  149. function FieldSummary(which : tquery): string;
  150. var tmpstr : string;
  151. begin
  152.  tmpstr := Which.findfield('TABLE_NAME').text+' : ';
  153.  tmpstr := tmpstr +Which.findfield('FIELD_NAME').text+' : ';
  154.  case Which.findfield('FIELD_TYPE').text[1] of
  155.        'S'  : tmpstr := tmpstr + ' String  '  ;
  156.        'I'  : tmpstr := tmpstr + ' Smallint'  ;
  157.        'N'  : tmpstr := tmpstr + ' Integer '  ;
  158.        'W'  : tmpstr := tmpstr + ' Word    '  ;
  159.        'L'  : tmpstr := tmpstr + ' Boolean '  ;
  160.        'F'  : tmpstr := tmpstr + ' Float   '  ;
  161.        'C'  : tmpstr := tmpstr + ' Currency'  ;
  162.        'B'  : tmpstr := tmpstr + ' BCD     '  ;
  163.        'D'  : tmpstr := tmpstr + ' Date    '  ;
  164.        'T'  : tmpstr := tmpstr + ' Time    '  ;
  165.        'A'  : tmpstr := tmpstr + ' DateTime'  ;
  166.        'Y'  : tmpstr := tmpstr + ' Bytes   '  ;
  167.        'V'  : tmpstr := tmpstr + ' VarBytes'  ;
  168.        'O'  : tmpstr := tmpstr + ' Blob    '  ;
  169.        'M'  : tmpstr := tmpstr + ' Memo    '  ;
  170.        'G'  : tmpstr := tmpstr + ' Graphic '  ;
  171.        end; {Case}
  172.  tmpstr := tmpstr + ' : ';
  173.  if Which.findfield('REQUIRED').asBoolean
  174.    then tmpstr := tmpstr + 'is Required : '
  175.    else tmpstr := tmpstr + 'not required: ';
  176.  if Which.findfield('FIELD_IDX').asBoolean
  177.    then tmpstr := tmpstr + 'is Index : '
  178.    else tmpstr := tmpstr + 'not Index: ';
  179.  result := tmpstr;
  180.  end;
  181.  
  182. Constructor TDictCTrl.Create(aOwner : tcomponent);
  183. begin
  184.   inherited create(aOwner);
  185.   fdbsg := tstringgrid.create(self);
  186.   FdbTableList := TstringList.create;
  187.   fTempdbMemo := Tdbmemo.create(self);
  188. end;
  189.  
  190. Destructor TDictCtrl.PutAway;
  191. begin
  192.   Fdbsg.free;
  193.   FdbTableList.free;
  194.   FtempdbMemo.free;
  195.   inherited destroy;
  196. end;
  197.  
  198.  
  199. Procedure TDictCtrl.ReadIniFile;
  200. begin
  201.   FIniFile := TiniFile.Create(appname+'.ini');
  202.   FCtrlDictName := FiniFile.ReadString('CtrlDict', 'current', appname+'.dbf');
  203.   FiniFile.free;
  204. end;
  205.  
  206. function TDictCtrl.getDictPath : tfilename;
  207. begin
  208.   result := extractFilePath(FCtrlDictName);
  209. end;
  210. procedure TDictCtrl.setDictPath( tmpstr : tfilename);
  211. begin
  212.   FCtrlDictName := tmpstr;
  213. end;
  214. function TDictCtrl.getDictTable : tfilename;
  215. begin
  216.   result := extractFileName(FCtrlDictName);
  217. end;
  218. procedure TDictCtrl.setDictTable (tmpstr : tfilename);
  219. begin
  220. end;
  221.  
  222.  
  223. Function GetBlobSize(Field: TBlobField): Longint;
  224. begin
  225.   with TBlobStream.Create(Field, bmRead) do
  226.   try
  227.     Result := Seek(0, 2);
  228.   finally
  229.     Free;
  230.   end;
  231. end;
  232.  
  233. Function GetBlobInfo(Field: TBlobField): String;
  234. var len : longint;
  235. begin
  236.   with TBlobStream.Create(Field, bmRead) do
  237.   try
  238.     len := Seek(0, 2);
  239.   finally
  240.     Free;
  241.   end;
  242.   if len = 0
  243.     then result := ''
  244.     else result := '['+intTostr(len)+']';
  245. end;
  246.  
  247. {================= Building string grid ===============}
  248.  
  249.  
  250. Function Getfirst255char(Field: TBlobField): String;
  251. var  len : longint;
  252.      p : array[0..256] of char;
  253. begin
  254.   with TBlobStream.Create(Field, bmRead) do
  255.   try
  256.     read(p, 255);
  257.     len := Seek(0, 2);
  258.   finally
  259.     Free;
  260.   end;
  261.   if len = 0
  262.     then result := ''
  263.     else result := strpas(p);
  264. end;
  265.  
  266.  
  267. function TDictCtrl.GetFieldAsString(const fieldname: string; var whichtable : ttable): string;
  268. var thisField : tfield;
  269. begin
  270.   thisField := whichTable.findfield(fieldname);
  271.   If thisField = nil
  272.     then result := 'nil'
  273.     else
  274.       case  thisField.datatype of
  275.        ftUnknown    : result := 'UNKNOWN';
  276.        ftString     : result := thisfield.text;
  277.        ftSmallint   ,
  278.        ftInteger    ,
  279.        ftWord       ,
  280.        ftBoolean    ,
  281.        ftFloat      ,
  282.        ftCurrency   ,
  283.        ftBCD        ,
  284.        ftDate       ,
  285.        ftTime       ,
  286.        ftDateTime   : result := thisfield.asString;
  287.        ftBytes      ,
  288.        ftVarBytes   ,
  289.        ftBlob       ,
  290.        ftMemo       ,
  291.        ftGraphic    : result := GetFirst255Char(TblobField(thisfield));
  292.       end;
  293. end;
  294.  
  295.  
  296. procedure TDictCtrl.OpenDictionary(const fullTableName : string;
  297.                                var whichdb : tdatabase; var whichtable : ttable;
  298.                                var whichQuery : tquery; var whichsource : tDataSource);
  299. begin
  300.   Screen.cursor := crHourglass;
  301.   FCtrlDictName := fullTableName;
  302.   try
  303.     WhichDB.close;
  304.     WhichDB.Params.clear;
  305.     WhichDB.Params.Add('PATH='+ExtractFilePath(FullTableName));
  306.     WhichDB.open;
  307.     WhichTable.DatabaseName:= WhichDB.databasename;
  308.     WhichTable.tablename := ExtractFileName(FullTableName);
  309.     WhichTable.Active:= True;
  310.     WhichSource.DataSet:= WhichTable;
  311.   except
  312.      on EdataBaseError do begin
  313.        MessageDlg('Could not open '+DictPath + ' '+DictTable, mtInformation, [mbOK], 0);
  314.        Screen.cursor := crDefault;
  315.        exit;
  316.        end;
  317.      end; {of exceptions}
  318.   {Now build and fill in DBSG, the data base dictionary string grid}
  319.   FillStringGRid(WhichTable);
  320.   FDBSGGood := true;
  321. {  WhichTable.close;
  322.   WhichDB.close;}
  323.   Screen.cursor := crDefault;
  324. end;
  325.  
  326. Procedure TDictCtrl.FillStringGrid(var WhichTable : Ttable);
  327. var
  328.   cur_row   : integer;
  329.   dictField : DDFOffsets;
  330. begin
  331.   try
  332.     WhichTable.first;
  333.     cur_row := 0;
  334.     fdbsg.free;
  335.     fdbsg := tstringGrid.create(self);
  336.     fDBSG.rowcount := WhichTable.recordCount;
  337.     fDBSG.colcount := WhichTable.fieldCount;
  338.     while not WhichTable.eof do begin
  339.       for dictField := ddfTable_Name to ddfFormula do
  340.          fDBSG.rows[cur_row].strings[ord(dictField)]
  341.            := GetFieldAsString(DictTableFieldNames[dictField], WhichTable);
  342.         inc(cur_row);
  343.         WhichTable.next;
  344.         end;
  345.       {end;}
  346.   except
  347.     on EdataBaseError do begin
  348.      screen.cursor := crDefault;
  349.      MessageDlg('Problem reading fields in from dictionary', mtInformation, [mbOK], 0);
  350.      exit;
  351.      end;
  352.   end; {of exceptions}
  353.   if whichTable.recordCount <> 0
  354.     then FillTableList;
  355. end;
  356.  
  357. Procedure TDictCtrl.FillTableList;
  358. var tablefound,
  359.     done : boolean;
  360.     thisTable : string;
  361.     i, j : integer;
  362. begin
  363.   FdbTableList.clear;
  364.   with FDBSG.cols[ord(ddfTable_name)] do begin
  365.     j := 0;
  366.     done := false;
  367.     if count = 0 then exit;
  368.     while not done do begin
  369.       TableFound := false;
  370.       thisTable := strings[j];
  371.       for i := 0 to FdbTableList.count -1 do
  372.         if FdbTableList.strings[i] = thistable
  373.           then begin
  374.             tablefound := true;
  375.             break;
  376.             end;
  377.       if not tablefound
  378.         then FdbTAbleList.add(thisTable);
  379.       inc(j);
  380.       if j = count -1
  381.         then done := true;
  382.       end; {while loop}
  383.     end; {with FDBSG}
  384. end;
  385.  
  386.  
  387.  
  388.  
  389. function TDictCtrl.SetCurrentFieldTo(const tablename, fieldname : string): boolean;
  390. var i : integer;
  391. begin
  392.   result := false;
  393.   for i := 0 to FDBSG.rowcount -1 do
  394.     if (upper(fDBSG.rows[i].strings[ord(ddfTable_name)]) = upper(tablename))
  395.         and (upper(fDBSG.rows[i].strings[ord(ddffield_name)]) = upper(fieldname))
  396.       then begin
  397.         fCurrentField := i;
  398.         FCurrentFieldName := fieldName;
  399.         FCurrentTableName := TableName;
  400.         result := true;
  401.         break;
  402.         end;
  403. end;
  404.  
  405. function TDictCtrl.getCurrentTableName : string;
  406. begin
  407.   if (FcurrentField > 0) and (FcurrentField < fDBSG.rowcount)
  408.       then result := fDBSG.rows[fCurrentField].strings[ord(ddfTable_name)]
  409.       else result := '';
  410. end;
  411.  
  412. function TDictCtrl.getCurrentFieldName : string;
  413. begin
  414.   if (FcurrentField > 0) and (FcurrentField < fDBSG.rowcount)
  415.       then result := fDBSG.rows[fCurrentField].strings[ord(ddfField_name)]
  416.       else result := '';
  417. end;
  418.  
  419.  
  420.  
  421. function TDictCtrl.getCurrentHint: string;
  422. begin
  423.   if (FcurrentField > 0) and (FcurrentField < fDBSG.rowcount)
  424.       then result := fDBSG.rows[fCurrentField].strings[ord(ddfHint)]
  425.       else result := '';  {probably should raise an exception here}
  426. end;
  427.  
  428. function TDictCtrl.Getrequired : boolean;
  429. begin
  430.   if (FcurrentField > 0) and (FcurrentField < fDBSG.rowcount)
  431.       then if Upper(fDBSG.rows[fCurrentField].strings[ord(ddfRequired)]) = 'TRUE'
  432.           then result := true
  433.           else result := false
  434.       else result := false;
  435.     { else probably should raise an exception here}
  436. end;
  437.  
  438. function TDictCtrl.GetMinVal : longint;
  439. begin
  440.   if (FcurrentField > 0) and (FcurrentField < fDBSG.rowcount)
  441.       then if fDBSG.rows[fCurrentField].strings[ord(ddfMinVal)] <> ''
  442.           then result := StrToInt(fDBSG.rows[fCurrentField].strings[ord(ddfMinVal)])
  443.           else result := 0
  444.       else result := 0;
  445.     { else probably should raise an exception here}
  446.     {also need to check that we did in fact have a number here}
  447.     {also not sure we want 0 to be the default...}
  448. end;
  449.  
  450. function TDictCtrl.GetMaxVal : longint;
  451. begin
  452.   if (FcurrentField > 0) and (FcurrentField < fDBSG.rowcount)
  453.       then if fDBSG.rows[fCurrentField].strings[ord(ddfMaxVal)] <> ''
  454.           then result := StrToInt(fDBSG.rows[fCurrentField].strings[ord(ddfMaxVal)])
  455.           else result := 0
  456.       else result := 0;
  457.     { else probably should raise an exception here}
  458.     {also need to check that we did in fact have a number here}
  459.     {also not sure we want 0 to be the default...}
  460. end;
  461.  
  462.  
  463.  
  464. function TDictCtrl.SetUpTable(var TableToSetUp : ttable): boolean;
  465. var fieldnum  : integer;
  466.     WhichTable : string;
  467.     foundit   : boolean;
  468. begin
  469.   result := false;
  470.   WhichTable := TableToSetUp.name;
  471.   with fDBSG do begin
  472.     for fieldnum := 0 to RowCount - 1 do
  473.       if Rows[0].strings[fieldnum] = whichTable
  474.         then
  475.            If SetFieldDefs(TableToSetUp, fieldnum)
  476.              then result := true;
  477.     end;
  478. end;
  479.  
  480. function TDictCtrl.setFieldDefs(var tableToDefine : Ttable; const fieldnum : integer): boolean;
  481. var
  482.   fldtype : TfieldType;
  483. begin
  484.   result := false;
  485.   result := SetUpCommon(tableToDefine, fieldnum);
  486.   if result = false then exit;
  487.   for fldtype := ftunknown to ftgraphic do
  488.     if FDBSG.cells[ord(ddfField_type), fieldnum] = FieldTypeStr[fldtype]
  489.         then break;
  490.     case fldtype of
  491.        ftString     : Result := SetUpString(tableToDefine, FieldNum);
  492.        ftSmallint  ,
  493.        ftInteger   ,
  494.        ftWord       : Result := DoNumbers(fldtype, tableToDefine, FieldNum);
  495.        ftBoolean    : Result := SeTUpBoolean(tableToDefine, FieldNum);
  496.        ftFloat     ,
  497.        ftCurrency  ,
  498.        ftBCD        : Result := DoNumbers(fldtype, tableToDefine, FieldNum);
  499.        ftDate       : Result := SetUpDate(tableToDefine, FieldNum);
  500.        ftTime       : Result := SetUpTime(tableToDefine, FieldNum);
  501.        ftDateTime   : Result := SetUpDateTime(tableToDefine, FieldNum);
  502.        ftBytes      : Result := SetUpBytes(tableToDefine, FieldNum);
  503.        ftVarBytes   : Result := SetUpVarBytes(tableToDefine, FieldNum);
  504.        ftBlob       : Result := SetUpBlob(tableToDefine, FieldNum);
  505.        ftMemo       : Result := SetUpMemo(tableToDefine, FieldNum);
  506.        ftGraphic    : Result := SetUpGraphic(tableToDefine, FieldNum);
  507.        end; {Case & for}
  508. end;
  509.  
  510. function TDictCtrl.SetUpCommon(var TableToDefine : ttable; const FieldNum : integer): boolean;
  511. var whichfield : string;
  512. begin with FDBSG do begin
  513.   whichfield := cells[ord(ddfField_name), FieldNum];
  514.   result := false;
  515.   try
  516.     if cells[ord(ddftag), FieldNum] <> ''
  517.       then TableToDefine.findField(whichField).tag := StrToint(cells[ord(ddftag), FieldNum]);
  518.     if cells[ord(ddfgrd_prompt), FieldNum] <> ''
  519.       then TableToDefine.findfield(whichField).DisplayLabel := cells[ord(ddfgrd_prompt), FieldNum];
  520.     if cells[ord(ddfgrd_width), FieldNum] <> ''
  521.       then TableToDefine.findfield(whichField).DisplayWidth := StrToInt(cells[ord(ddfgrd_width), FieldNum]);
  522.     if cells[ord(ddfEditMask), FieldNum] <> ''
  523.       then TableToDefine.findField(whichfield).EditMask
  524.               := cells[ord(ddfEditMask), FieldNum];
  525.     if upper(cells[ord(ddfrequired) ,FieldNum]) = 'TRUE'
  526.       then TableToDefine.findfield(whichfield).required := true
  527.       else TableToDefine.findField(whichField).required := false;
  528.     result := true;
  529.    except
  530.     on E: EConvertError do
  531.      MessageDlg('Error in '+WhichField+': Not a number ' + E.Message, mtInformation, [mbOK], 0);
  532.    else
  533.      MessageDlg('Unknown error in SetUpCommon for '+WhichField, mtInformation, [mbOK],0);
  534.    end;  {try..except}
  535.   end; {with FDBSG}
  536. end;
  537.  
  538.  
  539. function TDictCtrl.SetUpString(var TableToDefine : ttable; const FieldNum : integer): boolean;
  540. var whichfield : string;
  541. begin with fDBSG do begin
  542.   whichfield := cells[ord(ddffield_name), FieldNum];
  543.   result := false;
  544.   try
  545.     if cells[ord(ddfscr_Fmt), FieldNum] <> ''
  546.       then TableToDefine.findField(whichfield).EditMask
  547.               := cells[ord(ddfscr_Fmt),FieldNum];
  548.     if cells[ord(ddfEditMask), FieldNum] <> ''
  549.       then TableToDefine.findField(whichfield).EditMask
  550.               := cells[ord(ddfEditMask), FieldNum];
  551.     if cells[ord(ddffield_len), FieldNum] <> ''
  552.       then TableToDefine.findField(whichField).size := StrToint(cells[ord(ddffield_len), FieldNum]);
  553.     result := true;
  554.    except
  555.     on E: EConvertError do
  556.      MessageDlg('Error in '+WhichField+': Not a number ' + E.Message, mtInformation, [mbOK], 0);
  557.    else
  558.      MessageDlg('Unknown error in SetUpCommon for '+WhichField, mtInformation, [mbOK],0);
  559.    end;  {try..except}
  560.   end;
  561. end;
  562.  
  563. function TDictCtrl.SetUpBoolean(var TableToDefine : ttable; const FieldNum : integer): boolean;
  564. var whichfield : string;
  565. begin with fDBSG do begin
  566.   whichfield := cells[ord(ddffield_name), FieldNum];
  567.   result := false;
  568.   try
  569.     if cells[ord(ddfValList), FieldNum] <> ''
  570.       then TBooleanField(TableToDefine.findField(whichfield)).DisplayValues
  571.             := cells[ord(ddfValList), FieldNum];
  572.     result := true;
  573.    except
  574.      MessageDlg('Unknown error in SetUpCommon for '+WhichField, mtInformation, [mbOK],0);
  575.    end;  {try..except}
  576.   end;
  577. end;
  578.  
  579.  
  580. function TDictCtrl.SetUpDate(var TableToDefine : ttable; const FieldNum : integer): boolean;
  581. begin
  582.   result := true;
  583. end;
  584.  
  585. function TDictCtrl.SetUpDateTime(var TableToDefine : ttable; const FieldNum : integer): boolean;
  586. begin
  587.   result := true;
  588. end;
  589.  
  590. function TDictCtrl.SetUpTime(var TableToDefine : ttable; const FieldNum : integer): boolean;
  591. begin
  592.   result := true;
  593. end;
  594.  
  595. function TDictCtrl.SetUpBytes(var TableToDefine : ttable; const FieldNum : integer): boolean;
  596. var whichfield : string;
  597. begin with fDBSG do begin
  598.   whichfield := cells[ord(ddffield_name), FieldNum];
  599.   result := false;
  600.   try
  601.     if cells[ord(ddfField_len), FieldNum] <> ''
  602.       then TBytesField(TableToDefine.findField(whichfield)).Size
  603.             := strToInt(cells[ord(ddfField_len), FieldNum]);
  604.     result := true;
  605.    except
  606.     on E: EConvertError do
  607.      MessageDlg('Field Size Error in '+WhichField+': Not a number ' + E.Message, mtInformation, [mbOK], 0);
  608.    else
  609.      MessageDlg('Unknown error in SetUpBytes for '+WhichField, mtInformation, [mbOK],0);
  610.    end;  {try..except}
  611.   end;
  612. end;
  613.  
  614. function TDictCtrl.SetUpVarBytes(var TableToDefine : ttable; const FieldNum : integer): boolean;
  615. var whichfield : string;
  616. begin with fDBSG do begin
  617.   whichfield := cells[ord(ddffield_name), FieldNum];
  618.   result := false;
  619.   try
  620.     if cells[ord(ddfField_len), FieldNum] <> ''
  621.       then TVarBytesField(TableToDefine.findField(whichfield)).Size
  622.             := strToInt(cells[ord(ddfField_len), FieldNum]);
  623.     {not checking to insure value is 0..64K}
  624.     result := true;
  625.    except
  626.     on E: EConvertError do
  627.      MessageDlg('Field Size Error in '+WhichField+': Not a number ' + E.Message, mtInformation, [mbOK], 0);
  628.    else
  629.      MessageDlg('Unknown error in SetUpVarBytes for '+WhichField, mtInformation, [mbOK],0);
  630.    end;  {try..except}
  631.   end;
  632. end;
  633.  
  634. function TDictCtrl.SetUpBlob(var TableToDefine : ttable; const FieldNum : integer): boolean;
  635. var whichfield : string;
  636. begin with fDBSG do begin
  637.   whichfield := cells[ord(ddffield_name), FieldNum];
  638.   result := false;
  639.   try
  640.     if cells[ord(ddfField_len), FieldNum] <> ''
  641.       then TBlobField(TableToDefine.findField(whichfield)).Size
  642.             := strToInt(cells[ord(ddfField_len), FieldNum]);
  643.     result := true;
  644.    except
  645.     on E: EConvertError do
  646.      MessageDlg('Field Size Error in '+WhichField+': Not a number ' + E.Message, mtInformation, [mbOK], 0);
  647.    else
  648.      MessageDlg('Unknown error in SetUpBlob for '+WhichField, mtInformation, [mbOK],0);
  649.    end;  {try..except}
  650.   end;
  651. end;
  652.  
  653. function TDictCtrl.SetUpMemo(var TableToDefine : ttable; const FieldNum : integer): boolean;
  654. var whichfield : string;
  655. begin with fDBSG do begin
  656.   whichfield := cells[ord(ddffield_name), FieldNum];
  657.   result := false;
  658.   try
  659.     if cells[ord(ddfField_len), FieldNum] <> ''
  660.       then TMemoField(TableToDefine.findField(whichfield)).Size
  661.             := strToInt(cells[ord(ddfField_len), FieldNum]);
  662.     result := true;
  663.    except
  664.     on E: EConvertError do
  665.      MessageDlg('Field Size Error in '+WhichField+': Not a number ' + E.Message, mtInformation, [mbOK], 0);
  666.    else
  667.      MessageDlg('Unknown error in SetUpMemo for '+WhichField, mtInformation, [mbOK],0);
  668.    end;  {try..except}
  669.   end;
  670. end;
  671.  
  672. function TDictCtrl.SetUpGraphic(var TableToDefine : ttable; const FieldNum : integer): boolean;
  673. var whichfield : string;
  674. begin with fDBSG do begin
  675.   whichfield := cells[ord(ddffield_name), FieldNum];
  676.   result := false;
  677.   try
  678.     if cells[ord(ddfField_len), FieldNum] <> ''
  679.       then TGraphicField(TableToDefine.findField(whichfield)).Size
  680.             := strToInt(cells[ord(ddfField_len), FieldNum]);
  681.     result := true;
  682.    except
  683.     on E: EConvertError do
  684.      MessageDlg('Field Size Error in '+WhichField+': Not a number ' + E.Message, mtInformation, [mbOK], 0);
  685.    else
  686.      MessageDlg('Unknown error in SetUpGraphic for '+WhichField, mtInformation, [mbOK],0);
  687.    end;  {try..except}
  688.   end;
  689. end;
  690.  
  691. function TDictCtrl.doNumbers(const whichtype : TfieldType; var TableToDefine : ttable; const FieldNum : integer): boolean;
  692. var whichfield : string;
  693. begin with fDBSG do begin
  694.   whichfield := cells[ord(ddffield_name), FieldNum];
  695.   result := false;
  696.   try
  697.       case whichtype of
  698.         ftSmallInt: begin
  699.                       if cells[ord(ddfMinVal), FieldNum] <> ''
  700.                         then TSmallIntField(TableToDefine.findField(whichField)).minvalue
  701.                                 := StrToInt(cells[ord(ddfMinVal), FieldNum]);
  702.                       if cells[ord(ddfMaxVal), FieldNum] <> ''
  703.                         then TSmallIntField(TableToDefine.findField(whichField)).maxvalue
  704.                                 := StrToInt(cells[ord(ddfMaxVal), FieldNum]);
  705.                       end;
  706.         ftInteger: begin
  707.                      if cells[ord(ddfMinVal), FieldNum] <> ''
  708.                        then TIntegerField(TableToDefine.findField(whichField)).minvalue
  709.                                := StrToInt(cells[ord(ddfMinVal), FieldNum]);
  710.                      if cells[ord(ddfMaxVal), FieldNum] <> ''
  711.                        then TIntegerField(TableToDefine.findField(whichField)).maxvalue
  712.                                := StrToInt(cells[ord(ddfMaxVal), FieldNum]);
  713.                      end;
  714.  
  715.         ftword : begin
  716.                   if cells[ord(ddfMinVal), FieldNum] <> ''
  717.                     then TWordField(TableToDefine.findField(whichField)).minvalue
  718.                             := StrToInt(cells[ord(ddfMinVal), FieldNum]);
  719.                   if cells[ord(ddfMaxVal), FieldNum] <> ''
  720.                     then TWordField(TableToDefine.findField(whichField)).maxvalue
  721.                             := StrToInt(cells[ord(ddfMaxVal), FieldNum]);
  722.                   end;
  723.         ftFloat: begin
  724.                   if cells[ord(ddfMinVal), FieldNum] <> ''
  725.                     then TFloatField(TableToDefine.findField(whichField)).minvalue
  726.                             := StrToInt(cells[ord(ddfMinVal), FieldNum]);
  727.                   if cells[ord(ddfMaxVal), FieldNum] <> ''
  728.                     then TFloatField(TableToDefine.findField(whichField)).maxvalue
  729.                             := StrToInt(cells[ord(ddfMaxVal), FieldNum]);
  730.                   if cells[ord(ddfField_len), FieldNum] <> ''
  731.                    then TFloatField(TableToDefine.findField(whichfield)).Precision
  732.                            := StrToInt(cells[ord(ddfField_len), FieldNum]);
  733.                              end;
  734.         ftCurrency : begin {ftCurrency}
  735.                       if cells[ord(ddfMinVal), FieldNum] <> ''
  736.                         then TCurrencyField(TableToDefine.findField(whichField)).minvalue
  737.                                 := StrToInt(cells[ord(ddfMinVal), FieldNum]);
  738.                       if cells[ord(ddfMaxVal), FieldNum] <> ''
  739.                         then TCurrencyField(TableToDefine.findField(whichField)).maxvalue
  740.                                 := StrToInt(cells[ord(ddfMaxVal), FieldNum]);
  741.                       if cells[ord(ddfField_len), FieldNum] <> ''
  742.                        then TCurrencyField(TableToDefine.findField(whichfield)).Precision
  743.                                := StrToInt(cells[ord(ddfField_len), FieldNum]);
  744.                      end;
  745.          ftBCD: begin
  746.                   if cells[ord(ddfMinVal), FieldNum] <> ''
  747.                     then TBCDField(TableToDefine.findField(whichField)).minvalue
  748.                             := StrToInt(cells[ord(ddfMinVal), FieldNum]);
  749.                   if cells[ord(ddfMaxVal), FieldNum] <> ''
  750.                     then TBCDField(TableToDefine.findField(whichField)).maxvalue
  751.                             := StrToInt(cells[ord(ddfMaxVal), FieldNum]);
  752.                   if cells[ord(ddfField_len), FieldNum] <> ''
  753.                    then TBCDField(TableToDefine.findField(whichfield)).Precision
  754.                            := StrToInt(cells[ord(ddfField_len), FieldNum]);
  755.                  end;
  756.            end; {Case }
  757.    except
  758.     on E: EConvertError do
  759.      MessageDlg('Error in '+WhichField+': Not a number ' + E.Message, mtInformation, [mbOK], 0);
  760.    else
  761.      MessageDlg('Unknown error in SetUpCommon for '+WhichField, mtInformation, [mbOK],0);
  762.    end;  {try..except}
  763.   end;   {with DBSG}
  764. end;
  765.  
  766.  
  767. {=================================== build table ===============================}
  768.  
  769. function TDictCtrl.BuildEmptyTable(var TableToBuild : ttable; const TableName : string): boolean;
  770.   {TableToBuild is assumed to be an empty, newly created table for which
  771.    databasename, tabletype, and tablename (same as given) have been set}
  772. var fieldnum : integer;
  773.     fldtype : TFieldType;
  774.     fieldname : string;
  775.     fieldlen  : integer;
  776.     IsIndex,
  777.     IsRequired   : boolean;
  778. begin
  779.   result := false;
  780.   TableToBuild.FieldDefs.clear;
  781.   TableToBuild.IndexDefs.clear;
  782.   with fDBSG do begin
  783.     for fieldnum := 0 to RowCount - 1 do
  784.       if cells[ord(ddfTable_name), fieldnum] = TableName
  785.         then begin
  786.           for fldtype := ftunknown to ftgraphic do
  787.             if cells[ord(ddfField_type), fieldnum] = FieldTypeStr[fldtype]
  788.                 then break;
  789.           fieldname := cells[ord(ddfField_name), fieldnum];
  790.           if upper(cells[ord(ddfrequired) ,FieldNum]) = 'TRUE'
  791.             then IsRequired := true
  792.             else IsRequired := false;
  793.           if upper(cells[ord(ddfField_idx) ,FieldNum]) = 'TRUE'
  794.             then IsIndex := true
  795.             else IsIndex := false;
  796.           case fldtype of
  797.              ftString     : fieldlen := StrToInt(cells[ord(ddfField_len),fieldnum]);
  798.              ftSmallint  ,
  799.              ftInteger   ,
  800.              ftWord      ,
  801.              ftBoolean   ,
  802.              ftFloat     ,
  803.              ftCurrency  ,
  804.              ftBCD       ,
  805.              ftDate      ,
  806.              ftTime      ,
  807.              ftDateTime  : fieldlen := 0;
  808.              ftBytes     ,
  809.              ftVarBytes  ,
  810.              ftBlob      ,
  811.              ftMemo      ,
  812.              ftGraphic   : fieldLen := StrToInt(cells[ord(ddfField_len), fieldnum]);
  813.              end; {Case}
  814.            with TableToBuild.FieldDefs do begin
  815.              try
  816.                add(fieldname, fldtype, fieldlen, IsRequired);
  817.                if IsIndex
  818.                  then TableToBuild.IndexDefs.add(fieldname, fieldname, [ixPrimary, ixUnique]);
  819.                except
  820.                  on E: EDBEngineError do begin
  821.                    messagedlg('Error with '+fieldname+': '+E.message, mtInformation, [mbOk],0);
  822.                    result := false;
  823.                    end; {on error}
  824.                end; {try..except}
  825.              end; {with FieldDefs}
  826.           end; {of is a field in this table}
  827.     end; {of with FDBSG}
  828.     try
  829.       TableToBuild.CreateTable;
  830.       result := true;
  831.      except
  832.        on E: EDBEngineError do begin
  833.          messagedlg('BDE error creating table '+ tablename + ': '+E.message, mtInformation, [mbOK],0);
  834.          messagedlg('there are '+ IntTostr(E.ErrorCount)+' errors.', mtInformation, [mbOK],0);
  835.          for fieldlen := 0 to E.errorCount -1 do
  836.            messagedlg('#'+IntToStr(fieldlen)+': '+ E.Errors[fieldlen].message, mtInformation, [mbOK],0);
  837.          result := false;
  838.          end;
  839.        end;
  840. end;
  841.  
  842.  
  843.  
  844.  
  845. {=====================================  misc ===================================}
  846.  
  847.  
  848.  
  849.  
  850. function openDB(var whichdb : tdatabase; var whichtable : ttable;
  851.                 var whichQuery : tquery; var whichsource : tDataSource;
  852.                 const pathname, tablename : string): boolean;
  853. begin
  854.   try
  855.     WhichDB.close;
  856.     WhichDB.Params.clear;
  857.     WhichDB.Params.Add('PATH='+PathName);
  858.     WhichDB.open;
  859.     WhichTable.DatabaseName:= WhichDB.databasename;
  860.     WhichTable.tablename := TableName;
  861.     WhichTable.Active:= True;
  862.     WhichSource.DataSet:= WhichTable;
  863.     WhichQuery.databaseName := WhichDB.databasename;
  864.     WhichQuery.dataSource := WhichSource;
  865.     WhichQuery.close;
  866.     WhichQuery.sql.clear;
  867.     WhichQuery.params.clear;
  868.     result := true;
  869.   except
  870.      on EdataBaseError do begin
  871.        screen.cursor := crDefault;
  872.        MessageDlg('Could not open '+pathname + ' '+tablename, mtInformation, [mbOK], 0);
  873.        result := false;
  874.        end;
  875.      end; {of exceptions}
  876. end;
  877.  
  878.    {
  879.            TIntegerField       Whole numbers in the range -2,147,483,648 to 2,147,483,647
  880.             TWordField  Whole numbers in the range 0 to 65535
  881.             TBooleanField       True or False values
  882.             TFloatField Real numbers with absolute magnitudes from 5.0*10-324 to 1.7*10308
  883.                             accurate to 15-16 digits
  884.             TCurrencyField      Currency values. The range and accuracy is the same as TFloatField
  885.             TBCDField   Real numbers with a fixed number of digits after the decimal point.
  886.                             Accurate to 18 digits. Range depends on the number of digits after the
  887.                              decimal point. [Paradox only]
  888.             TDateField  Date value
  889.             TTimeField  Time value
  890.             TDateTimeField      Date and time value
  891.             TBytesField Arbitrary data field without a size limit
  892.             TVarBytesField      Arbitrary data field up to 65535 characters, with the actual length stored
  893.                             in the first two bytes
  894.             TBlobField  Arbitrary data field without a size limit
  895.             TMemoField  Arbitrary length text
  896.             TGraphicField       Arbitrary length graphic, such as a bitmap
  897.              }
  898.  
  899. procedure Register;
  900. begin
  901.   RegisterComponents('Synature', [tdictctrl]);
  902. end;
  903.  
  904.  
  905. Initialization
  906.  
  907. dictCtrl := tdictCtrl.create(application);
  908.  
  909. DBSGExists := false;
  910.  
  911. end.
  912.  
  913.  
  914. {
  915.     pbuffer : pointer;
  916.     pRecBufr : pointer;
  917.     dbicallrslt : DBIResult;
  918.     BLOBlen,
  919.     BLOBread : longint;
  920.  
  921.          begin
  922.            getmem(pbuffer, sizeof(buffer));
  923.            getmem(pRecBufr, sizeof(buffer));
  924.            dbiCallRslt := DbiOpenBlob(whichTable.handle, pRecBufr, thisField.fieldno,dbireadonly);
  925.            if dbiCallRslt = DBIERR_NONE
  926.               then begin
  927.                 dbicallRslt := DbiGetBlobSize(whichTable.handle,pRecBufr,thisField.fieldno,BLOBlen);
  928.                 dbiCallRslt := DbiGetBlob(whichTable.handle,pRecBufr, thisField.fieldno, 0, sizeof(buffer), pbuffer, BLOBread);
  929.                 if (dbiCallRslt = DBIERR_NONE) or (dbiCallRslt = DBIERR_ENDOFBLOB)
  930.                  then begin
  931.                     dbicallRslt := DbiGetBlobSize(whichTable.handle,pRecBufr,thisField.fieldno,BLOBlen);
  932.                     if dbicallRslt = DBIERR_NONE
  933.                       then result := 'z'+intTostr(BLOBlen)
  934.                       else result := 'zz';
  935.                     end
  936.                    else case
  937.                     dbiCallRslt of
  938.                       DBIERR_INVALIDBLOBHANDLE : result := 'y handle';
  939.                       DBIERR_INVALIDPARAM : result := 'y param';
  940.                       DBIERR_NOTABLOB : result := 'y not blob';
  941.                       DBIERR_INVALIDBLOBOFFSET : result := 'y offset';
  942.                       DBIERR_TABLEREADONLY : result := 'y read';
  943.                       end;
  944.                 end
  945.               else case dbiCallrslt of
  946.                       DBIERR_INVALIDHNDL : result := 'x handle';
  947.                       DBIERR_INVALIDPARAM : result := 'x param';
  948.                       DBIERR_OUTOFRANGE : result := 'x range';
  949.                       DBIERR_BLOBOPENED : result := 'x open';
  950.                       DBIERR_NOTABLOB : result := 'x not blob';
  951.                       DBIERR_OPENBLOBLIMIT : result := 'x limit';
  952.                       DBIERR_TABLEREADONLY : result := 'x read';
  953.                       end;
  954.            dbiCallRslt := DbiFreeBlob(whichTable.handle, pRecBufr, thisField.fieldno);
  955.  
  956.            freemem(pbuffer, sizeof(buffer));
  957.            freemem(pRecBufr, sizeof(buffer));
  958.            end;}
  959.  
  960.  
  961.